<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <h3>compile</h3>
      <p>{{ a }}</p>
      <p>{{ b }}</p>
    </div>

    <script>
      const str = document.querySelector("#app").innerHTML;
      const data = {
        a: 3,
        b: 4,
      };

      const compile = (node) => {
        // 获取里面的所有的子元素
        const children = [...node.children];
        // 写一个正则，去匹配装大括号
        const reg = /\{\{(.*)\}\}/;
        children.forEach((child) => {
          // 里面的内容包含了双大括号
          if (reg.test(child.textContent)) {
            child.innerHTML = data[RegExp.$1.trim()];
          }
        });
      };

      compile(document.querySelector("#app"));

      const observer = (data, item, value) => {
        Object.defineProperty(data, item, {
          get() {
            return value;
          },
          set(val) {
            value = val;
            document.querySelector("#app").innerHTML = str;
            // 可以在这个地方去重新渲染页面，从而实现响应式
            compile(document.querySelector("#app"));
          },
        });
      };

      Object.keys(data).forEach((item) => {
        // data[item]就是这个属性的初始值
        observer(data, item, data[item]);
      });

      setInterval(() => {
        data.a++;
      }, 1000);
    </script>
  </body>
</html>
